www.gusucode.com > 《C++高级语言程序设计》PPT及全书例子源代码-源码程序 > 《C++高级语言程序设计》PPT及全书例子源代码-源码程序/code/C++例题程序/第4章/复件 s4_12/sclass4_12_Node.cpp

    //Download by http://www.NewXing.com
//类的实现文件
//文件名:ch4_12\sclass4_12_Node.cpp

#include "sclass4_12_Node.h"    /*包含类定义头文件*/

//Node无参构造函数
//Node::Node()
//{
//	m_lpszChar = NULL;
//	m_iValue = 0;
//	cout << "调用了无参构造函数Node: " <<  endl;
//}

//Node带参构造函数
Node::Node(char *lpszChar, int iValue)					//节点构造函数
{
	m_lpszChar = new char[strlen(lpszChar)+1];			//new节点名字空间。
	if( m_lpszChar==NULL )
	{
		cout << "内存分配失败。" << endl;
		exit(1);										//内存分配失败,退出。
	}
	strcpy(m_lpszChar, lpszChar);
	m_iValue = iValue;									//节点值初为0
	cout << "调用了带参构造函数Node: " << m_lpszChar << endl;
}

//Node的拷贝构造函数
Node::Node(const Node &oNode)
{
	m_lpszChar = new char[strlen(oNode.m_lpszChar)+1];	//new节点名字空间。
	if( m_lpszChar==NULL )
	{
		cout << "内存分配失败。" << endl;
		exit(1);
	}
	strcpy(m_lpszChar, oNode.m_lpszChar);
	m_iValue = oNode.m_iValue;							//节点值初为0
	cout << "调用了拷贝构造函数Node:" << m_lpszChar << endl;
}

//Node的析构函数
Node::~Node()
{
	cout << "调用了析构函数Node: " << m_lpszChar << endl;
	delete m_lpszChar;		//当m_lpszChar==NULL时,也可以delete,不会出错。
}

//Node的赋值运算符重载
Node & Node::operator=(const Node &oNode)
{
	if (this == &oNode)									//判断是否自己赋值自己
	{
		return *this;
	}
	delete m_lpszChar;									//释放原字符数组空间
	m_lpszChar = new char[strlen(oNode.m_lpszChar)+1];	//new字符数组空间。
	if( m_lpszChar==NULL )
	{
		cout << "内存分配失败。" << endl;
		exit(1);
	}
	strcpy(m_lpszChar, oNode.m_lpszChar);
	m_iValue = oNode.m_iValue;							//节点值初为0
	cout << "调用了重载'='运算符Node:" << m_lpszChar << endl;
	return *this;
}

//CNodeArray类的构造函数
CNodeArray::CNodeArray(int iTotalNodeNum)				//节点数组构造函数。
{
	for (int i=0; i<iTotalNodeNum; i++)
	{
		m_pNode[i] = NULL;				//指针数组初始化,数组内的指针全部指向NULL。
	}
    m_aLength = iTotalNodeNum;							//数组长度设置。
	m_aCurrentTop = 0;									//当前节点设置为0。
	cout << "调用了构造函数CNodeArray:" << endl;
}

//CNodeArray的拷贝构造函数。const引用作参数,可保证实参的安全性。
CNodeArray::CNodeArray(const CNodeArray &oCNodeArray)
{
	//在[0~m_aCurrentTop-1]之间,有Node节点,所以需要新建节点。
	for (int i=0; i<oCNodeArray.m_aCurrentTop; i++)
	{
		//创建一个新节点,并将oCNodeArray上对应节点的内容复制过来。
		m_pNode[i] = new Node(oCNodeArray.m_pNode[i]->m_lpszChar, 
								oCNodeArray.m_pNode[i]->m_iValue);	
		if (m_pNode[i] == NULL)							//判断内存分配是否成功。
		{
			cout << "内存分配失败!" << endl;
			exit(1);
		}
	}
	//在[m_aCurrentTop~m_aLength-1]之间,没有Node节点,全为NULL。
	for (i=oCNodeArray.m_aCurrentTop; i<oCNodeArray.m_aLength; i++)
	{
		m_pNode[i] = NULL;
	}
	m_aLength = oCNodeArray.m_aLength;					//复制数组长度的值。
	m_aCurrentTop = oCNodeArray.m_aCurrentTop;			//复制当前节点标号值。
	cout << "调用了拷贝构造函数CNodeArray:" << endl;
}

//析构函数。
CNodeArray::~CNodeArray(void)							//析构函数
{
	for (int i=0; i<m_aCurrentTop; i++)
	{
		delete m_pNode[i];								//自动调用~Node()。
	}
	cout << "调用了析构函数CNodeArray。" << endl;
}

//插入一个节点。插入位置在m_aCurrentTop处。这里通过指针数组里的指针操作其所指向的节点。
//其插入和删除有点类似堆栈的性质:只在top端,插入,删除。
bool CNodeArray::Insert(const Node &oNode)	//插入一个节点
{
	//将要插入的节点复制到节点数组中。
	m_pNode[m_aCurrentTop] = new Node(oNode.m_lpszChar, oNode.m_iValue);
	if (m_pNode[m_aCurrentTop] == NULL)
	{
		cout << "创建节点失败!" << endl;
		exit(1);
	}
	m_aCurrentTop++;						//将当前节点值m_aCurrentTop+1,下一次插入的位置。
	cout << "插入了一个节点: " << oNode.m_lpszChar << endl;
	return true;
}

//删除一个节点。每次删除都删除m_aCurrentTop-1的对应节点。相当于节点出栈。
bool CNodeArray::Del(void)					//删除一个节点
{
	if (!IsEmpty())							//如果指针数组非空,则执行删除操作。
	{
		m_aCurrentTop--;					//首先将当前节点值减1。当前节点实际上还没有内容。
		cout << "删除的节点名字为:" << m_pNode[m_aCurrentTop]->m_lpszChar << endl; 
		delete m_pNode[m_aCurrentTop];		//释放当前节点
		return true;
	}
	else 
	{
		cout << "节点数组为空。不能够执行删除操作。Is Empty\n";
		return false;
	}
}

//判断节点指针数组中是否有节点。
bool CNodeArray::IsEmpty(void)					
{
	if (m_aCurrentTop == 0) 
	{
		return true;									//为空返回真。
	}
	else 
	{
		return false;									//不为空,返回假。
	}
}

//CNodeArray的','运算符重载。
const CNodeArray & CNodeArray::operator,(const CNodeArray &oCNodeArray)
{
	return oCNodeArray;									//直接返回第二操作数。
}

//CNodeArray的'[]'运算符重载。
char *CNodeArray::operator[](int i)
{
	if ((i < m_aCurrentTop)&&(m_aCurrentTop >=0))
	{
		return m_pNode[i]->m_lpszChar;					//返回第i个节点的字符串。
	}
	else 
	{
		return ("数组越界。");
	}
}

//赋值运算符重载。其重载函数体与拷贝构造函数相同,可调用完成。但重载赋值运算符需要
//首先释放,调用对象的相关动态内存。
CNodeArray & CNodeArray::operator=(const CNodeArray &oCNodeArray)
{
	if (this == &oCNodeArray)	//首先判断是否自己赋值给自己
	{
		return *this;
	}
	//这里需要考虑两个对象的m_aLength属性是否相同,是否一样大,否则会产生数组越界的问题。
	//这里的指针数组是非动态的,不可调整大小。
	if (m_aLength != oCNodeArray.m_aLength)
	{
		cout << "复制出错。" << endl;
		return *this;
	}

	//首先进行释放工作,释放this对象所使用到的所有动态内存空间。
	for (int i=0; i<m_aCurrentTop; i++)
	{
		delete m_pNode[i];	//释放指针数组中的每个指针所指向的动态内存空间,=NULL。
		//m_pNode[i] = NULL;
	}

	//此后可进行对象复制工作。此处是一个深度复制过程,在复制中需要新建(new)Node
	//类型的对象数组空间,所以用了Node的构造函数。
	//在[0~m_aCurrentTop-1]之间,有Node节点,所以需要新建节点。
	for (i=0; i<oCNodeArray.m_aCurrentTop; i++)
	{
		//创建一个新节点,并将oCNodeArray上对应节点的内容复制过来。
		m_pNode[i] = new Node(oCNodeArray.m_pNode[i]->m_lpszChar, oCNodeArray.m_pNode[i]->m_iValue);	
		if (m_pNode[i] == NULL)	//判断内存分配是否成功。
		{
			cout << "内存分配失败!" << endl;
			exit(1);
		}
	}
	//在[m_aCurrentTop~m_aLength-1]之间,全为NULL。
	for (i=oCNodeArray.m_aCurrentTop; i<oCNodeArray.m_aLength; i++)
	{
		m_pNode[i] = NULL;
	}
	m_aLength = oCNodeArray.m_aLength;			//复制数组长度的值。
	m_aCurrentTop = oCNodeArray.m_aCurrentTop;	//复制当前节点标号值。
	cout << "调用重载运算符'='CNodeArray:" << endl;
	return *this;
}

//重载new
void *CNodeArray::operator new(size_t size)
{
	cout << "自定义的 CNodeArray new\n";
	return malloc(size);
}

//重载delete
void CNodeArray::operator delete(void *p)
{
	cout << "自定义的 CNodeArray delete\n";
	free(p);
}

//重载输出运算符,
ostream & operator << (ostream & scout, CNodeArray obj)
{
	scout << obj.m_pNode[obj.m_aCurrentTop-1]->m_lpszChar << ",";
	scout << obj.m_pNode[obj.m_aCurrentTop-1]->m_iValue << ",";
	scout << obj.m_aLength << ","; 
	scout << obj.m_aCurrentTop << endl; 
	return scout; 
}

//重载输入运算符  		 
istream & operator >> (istream &scin, CNodeArray &obj)
{
	int iTemp = 0;
	char *lpszChar = new char[100];
	cout << "请输入操作下标:";
	scin >> iTemp;
	cout << "请输入节点值:";
	scin >> obj.m_pNode[iTemp]->m_iValue;
	cout << "节点原名字为:" << obj.m_pNode[iTemp]->m_lpszChar << endl;
	cout << "请输入节点新名字:" << endl;
	scin.get();
	scin.getline(lpszChar,20);					//从输入流中取得一行,新节点名字。
	delete obj.m_pNode[iTemp]->m_lpszChar;		//释放原来的内存空间。
	obj.m_pNode[iTemp]->m_lpszChar = lpszChar;	//指向新的内存空间。
	cout << "现名字为:" << obj.m_pNode[iTemp]->m_lpszChar << endl;
	return scin;
}